<?php


namespace BoojasrFramework\ServicesContainer;



use BoojasrFramework\PackageManage;
use BoojasrFramework\Tools;
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
use Symfony\Component\Cache\CacheItem;

class Kernel implements KernelInterface
{
    public static function instance(){
        static $object;
        if (!$object){
            $object = new static();
        }
        return $object;
    }

    /**
     * @var ContainerInterface
     */
    protected $container;

    protected $env;

    protected $isInit = false;

    public function boot(){
        $this->initializeContainer();
        $this->buildContainer();
        $this->bootPackage();
    }

    public function bootPackage(){
        $package = $this->getPackageManage();
        $package->setContainer($this->getContainer(false));
        $package->boot();
    }

    public function getPackageManage(){
        static $package;
        if (!$package) $package = new PackageManage();
        return $package;
    }

    /**
     * 初始化服务容器
     */
    protected function initializeContainer(){
        $this->container = new ContainerBuilder();
    }

    protected function buildContainer(){
        $cacheContainer = $this->getCacheContainer();
        if (!$cacheContainer){
            $container = $this->getContainer(false);
            $compile = $container->getCompiler();
            $compile->compile($container);
            $this->setCacheContainer($container);
        }else{
            $this->container = $container = $cacheContainer;
        }
        $container->set("service_kernel",$this);
        ServicesClassFactory::setContainer($container);
        $this->isInit = true;
    }

    private function getAdapter($type="file"){
        static $cache;
        if (!$cache||!isset($cache[$type])){
            $cache[$type] = new FilesystemAdapter("boojasr",0,dirname(__DIR__,2)."/boom/cache/kernel");
        }
        return $cache[$type];
    }

    protected function getCacheContainer(){
        if ($this->getEnv() != "prod"){
            return false;
        }
        try {
            $cache = $this->getAdapter();
            /** @var CacheItem $cacheItem */
            $cacheItem = $cache->getItem("boojasr_container");
            $cacheValue = $cacheItem->get();
            if ($cacheValue){
                return unserialize($cacheValue);
            }
        }catch (\Exception $e){}
        return false;
    }

    protected function setCacheContainer($container){
        if ($this->getEnv() != "prod"){
            return false;
        }
        try {
            $cache = $this->getAdapter();
            /** @var CacheItem $cacheItem */
            $cacheItem = $cache->getItem("boojasr_container");
            $cacheItem->set(serialize($container));
            $cache->save($cacheItem);
            return true;
        }catch (\Exception $e){}
        return false;
    }


    /**
     * @return Container
     */
    public function getContainer($hasInit=true)
    {
        if ($hasInit){
            if (!$this->isInit){
                throw new \LogicException('容器还未进行初始化');
            }
        }
        $static_container = &Tools::beau_static(__FUNCTION__);
        if ($static_container){
            $this->container = $static_container;
        }

        if (!$this->container) {
            throw new \LogicException('无法从未启动的内核中检索容器。');
        }

        $static_container = $this->container;
        return $this->container;
    }

    public function handle( $request, $type = self::MASTER_REQUEST, $catch = true)
    {
        $this->boot();
        return $this->getHttpKernel()->handle($request,$type,$catch);
    }

    /**
     * @return HttpKernel
     */
    public function getHttpKernel()
    {
        return $this->container->get('http_kernel');
    }

    /**
     * @return mixed
     */
    public function getEnv()
    {
        return $this->env;
    }

    /**
     * @param mixed $env
     */
    public function setEnv($env): void
    {
        $this->env = $env;
    }

}
